package com.swss.g.base.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.swss.g.base.BaseDAO;
import com.swss.util.Pagination;

public abstract class BaseDAOImpl<T extends Serializable> extends
		HibernateDaoSupport implements BaseDAO<T> {

	// 获取当前类  
	private Class<T> persistentClass;

	@SuppressWarnings("unchecked")
	public BaseDAOImpl() {

		this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];

	}

	public Class<T> getPersistentClass() {
		return persistentClass;
	}

	public String beanName() {
		// System.out.println(this.getPersistentClass().getName());
		return getPersistentClass().getName().split("\\.")[5];
	}

	// 按example查询
	public List<T> findByEg(T example) {
		// TODO Auto-generated method stub
		return null;
	}

	// 按id查询一条数据
	@SuppressWarnings("unchecked")
	public T get(Serializable id) throws Exception {
		// TODO Auto-generated method stub

		return (T) this.getHibernateTemplate().get(this.getPersistentClass(),
				id);
	}

	// 按hql查询多条
	@SuppressWarnings("unchecked")
	public List<T> findByHql(final String hql, final Pagination pagination) {
		List list = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query = session.createQuery(hql.toString());

				if (pagination != null && pagination.isUsepage()) {
					int start = (pagination.getPageno() - 1)
							* pagination.getPagesize();
					int rowCount = pagination.getPagesize();
					query.setFirstResult(start);
					query.setMaxResults(rowCount);
				}
				
				List list = query.list();
				// 清楚缓存，待观察学习
				session.flush();
				session.clear();
				return list;

			}
		});
		return list;
	}

	@SuppressWarnings("unchecked")
	public List<T> findByHql(final String hql) {
		Pagination pagination = new Pagination();
		pagination.setUsepage(false); 
		return this.findByHql(hql, pagination);
	}
   
	//查询单个对象
	@SuppressWarnings("unchecked")
	public T findOneByHql(final String hql) {
		if (this.findByHql(hql).size() == 0)
			return null;
		else
			return (T) this.findByHql(hql).get(0);
	}

	// 按example查询
	@SuppressWarnings("unchecked")
	public List<T> findByExample(T example, Pagination pagination) {
		if (pagination != null && pagination.isUsepage()) {
			int start = (pagination.getPageno() - 1) * pagination.getPagesize();
			int rowCount = pagination.getPagesize();

			return this.getHibernateTemplate().findByExample(example, start,
					rowCount);
		} else {

			return this.getHibernateTemplate().findByExample(example);
		}
	}

	@SuppressWarnings("unchecked")
	public List<T> findByCriteria(T example, final Pagination pagination) {

		return null;

	}

	// 保存一条
	public T save(T entity) {

		this.getHibernateTemplate().save(entity);
		return entity;
	}

	public T update(T entity) {
		
		this.getHibernateTemplate().update(entity);
		return entity;
	}

	// 保存或更新
	public T saveOrUpdate(T entity) {
		this.getHibernateTemplate().saveOrUpdate(entity);
		return entity;
	}

	public void saveOrUpdateAll(List<T> list) {
		for (T entity : list) {
			this.saveOrUpdate(entity);
		}
	}

	// 删除
	public void delete(T entity) {
		
		this.getHibernateTemplate().delete(entity);
	}

	public void deleteAll(List<T> entities) {
		this.getHibernateTemplate().deleteAll(entities);
	}

	public int findCount() {
		Object count = this.getHibernateTemplate().execute(
				new HibernateCallback() {

					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						// TODO Auto-generated method stub
						return session.createQuery(
								"SELECT COUNT(*) FROM " + beanName())
								.uniqueResult();
					}

				});
		return Integer.parseInt(count.toString());
		
	}
   
	public int findCount(final String hql) {
		Object count = this.getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						// TODO Auto-generated method stub
						return session.createQuery("SELECT COUNT(*) " + hql).uniqueResult();
					}

				});
		return Integer.parseInt(count.toString());
	}
   //资产数量统计
	public Long  findAstCount(final String hql,final String astType) {
		Object count = this.getHibernateTemplate().execute(
				new HibernateCallback() {

					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						// TODO Auto-generated method stub
						String sql="SELECT sum("+astType+".astCount) " + hql;
						Long AstCount=(Long) session.createQuery(sql).uniqueResult();
						return AstCount==null?0:AstCount;
					}
				});
		return (Long) count;
	}
	//资产金额统计
	public Double findAstAmount(final String hql,final String astType) {
		Object count = this.getHibernateTemplate().execute(
				new HibernateCallback() {

					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						// TODO Auto-generated method stub
						String sql="SELECT sum("+astType+".amount) " + hql;
						Double AstAmount=(Double) session.createQuery(sql).uniqueResult();
						return AstAmount==null?0:AstAmount;
					}
				});
		return Double.parseDouble(count.toString());

	}
	@SuppressWarnings("unchecked")
	public List<T> findAll(Pagination pagination) {
		return this.findByHql("FROM " + beanName() + " ORDER BY "
				+ pagination.getOrderBy() + " " + pagination.getOrderType(),
				pagination);
	}

	// 按crit方式查询
	// 使用范例
	// List<Order> o = new ArrayList<Order>();
	// o.add(Order.asc("aa"));
	//
	// List<Criterion> c = new ArrayList<Criterion>();
	// c.add((Criterion) Order.asc("a"));
	// c.add(Restrictions.like("name", "Fritz%"));
	// User u = new User();
	// c.add(Example.create(u));
	//
	// this.findByCriteria(pagination, c, Projections.projectionList().add(
	// Projections.rowCount()), o);
	@SuppressWarnings("unchecked")
	public Pagination<T> findByCriteria(final Pagination pagination,
			final List<Criterion> criterions, final Projection projection,
			final List<Order> orders) {
		return (Pagination) this.getHibernateTemplate().execute(
				new HibernateCallback() {

					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						// TODO Auto-generated method stub
						Criteria criteria = session
								.createCriteria(getPersistentClass());

						// criterions
						if (criterions != null) {
							for (Criterion c : criterions) {
								criteria.add(c);
							}
						}

						// 投影
						criteria.setProjection(projection);

						if (projection == null) {

							criteria
									.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
						}

						// 排序

						if (orders != null) {
							for (Order order : orders) {
								criteria.addOrder(order);
							}
						}

						// 判断和使用分页类
						if (pagination == null) {
							Pagination pagination = new Pagination<T>();
							pagination.setUsepage(false);
						}

						if (pagination.isUsepage()) {
							int start = (pagination.getPageno() - 1)
									* pagination.getPagesize();
							int rowCount = pagination.getPagesize();
							criteria.setFirstResult(start);
							criteria.setMaxResults(rowCount);
						}

						// 汇总数据
						pagination.setRowcount(((Number) criteria
								.setProjection(Projections.rowCount())
								.uniqueResult()).intValue());
						pagination.setResult(criteria.list());
						return pagination;
					}

				});

	}

	@SuppressWarnings("unchecked")
	public T findOneByExample(T example) {
		List list =this.getHibernateTemplate().findByExample(example);
		if(list.size()==0){
			return null;
		}
		return (T) this.getHibernateTemplate().findByExample(example).get(0);
	}
	
	public void saveAll(final List<T> list){
		this.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				// TODO Auto-generated method stub
				for (T t : list) {
					session.save(t);
					session.flush();
					session.clear();
				}
				return null;
			}
		});
	}
}
